using Microsoft.Extensions.Logging;
using Renci.SshNet;
using SumerCoreDevOps.ExecuteNodeApi.Services;
using SumerCoreDevOps.Infrastructure.Security;
using SumerCoreDevOps.Shared.Models.Messages;
using System.Text.Json;

namespace SumerCoreDevOps.ExecuteNodeApi.Handlers;

/// <summary>
/// Docker 远程部署处理器（部署到指定主机）
/// </summary>
public class DockerDeployRemoteHandler : IStepHandler
{
    private readonly ILogger<DockerDeployRemoteHandler> _logger;
    private readonly TaskExecutor _taskExecutor;

    public DockerDeployRemoteHandler(
        ILogger<DockerDeployRemoteHandler> logger,
        TaskExecutor taskExecutor)
    {
        _logger = logger;
        _taskExecutor = taskExecutor;
    }

    public async Task<StepExecutionResult> ExecuteAsync(WorkflowStepDispatchMessage message)
    {
        try
        {
            var config = JsonSerializer.Deserialize<DockerDeployRemoteConfig>(message.StepConfig);

            if (config == null || string.IsNullOrEmpty(config.RemoteHost))
            {
                return new StepExecutionResult
                {
                    Success = false,
                    ErrorMessage = "Docker 远程部署配置无效：必须指定 RemoteHost"
                };
            }

            await SendLog(message, $"开始部署 Docker 镜像到远程主机: {config.RemoteHost}");

            // 获取 SSH 凭证
            string? username = null;
            string? password = null;
            string? privateKeyPath = null;

            if (message.EncryptedCredentials.TryGetValue(Shared.Enums.CredentialType.Git, out var encryptedCred))
            {
                try
                {
                    var decryptedJson = EncryptionHelper.Decrypt(encryptedCred);
                    var sshCredential = JsonSerializer.Deserialize<SshCredential>(decryptedJson);

                    if (sshCredential != null)
                    {
                        username = sshCredential.Username;
                        password = sshCredential.Password;
                        privateKeyPath = sshCredential.PrivateKeyPath;
                        await SendLog(message, $"SSH 凭证解密成功，用户: {username}");
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogWarning(ex, "SSH 凭证解密失败");
                    return new StepExecutionResult
                    {
                        Success = false,
                        ErrorMessage = "SSH 凭证解密失败"
                    };
                }
            }
            else
            {
                // 使用配置中的凭证
                username = config.SshUsername;
                password = config.SshPassword;
            }

            if (string.IsNullOrEmpty(username))
            {
                return new StepExecutionResult
                {
                    Success = false,
                    ErrorMessage = "未提供 SSH 用户名"
                };
            }

            // 建立 SSH 连接
            await SendLog(message, $"连接到远程主机: {config.RemoteHost}:{config.SshPort}");

            Renci.SshNet.ConnectionInfo connectionInfo;
            if (!string.IsNullOrEmpty(privateKeyPath) && File.Exists(privateKeyPath))
            {
                // 使用私钥认证
                var keyFile = new PrivateKeyFile(privateKeyPath, password);
                connectionInfo = new Renci.SshNet.ConnectionInfo(
                    config.RemoteHost,
                    config.SshPort,
                    username,
                    new PrivateKeyAuthenticationMethod(username, keyFile));
            }
            else if (!string.IsNullOrEmpty(password))
            {
                // 使用密码认证
                connectionInfo = new Renci.SshNet.ConnectionInfo(
                    config.RemoteHost,
                    config.SshPort,
                    username,
                    new PasswordAuthenticationMethod(username, password));
            }
            else
            {
                return new StepExecutionResult
                {
                    Success = false,
                    ErrorMessage = "未提供 SSH 密码或私钥"
                };
            }

            using var sshClient = new SshClient(connectionInfo);
            sshClient.Connect();

            await SendLog(message, "SSH 连接成功");

            // 构建完整的镜像名称
            var fullImageName = string.IsNullOrEmpty(config.Registry)
                ? $"{config.ImageName}:{config.Tag ?? "latest"}"
                : $"{config.Registry}/{config.ImageName}:{config.Tag ?? "latest"}";

            // 1. 检查 Docker 是否安装
            await SendLog(message, "检查远程主机 Docker 环境...");
            var dockerVersion = ExecuteCommand(sshClient, "docker --version");
            if (string.IsNullOrEmpty(dockerVersion))
            {
                return new StepExecutionResult
                {
                    Success = false,
                    ErrorMessage = "远程主机未安装 Docker"
                };
            }
            await SendLog(message, $"Docker 版本: {dockerVersion}");

            // 2. 拉取镜像（如果需要从 Registry）
            if (!string.IsNullOrEmpty(config.Registry))
            {
                await SendLog(message, $"从 Registry 拉取镜像: {fullImageName}");

                // 如果有 Docker 凭证，先登录
                if (message.EncryptedCredentials.TryGetValue(Shared.Enums.CredentialType.Docker, out var dockerCred))
                {
                    try
                    {
                        var decryptedJson = EncryptionHelper.Decrypt(dockerCred);
                        var dockerCredential = JsonSerializer.Deserialize<DockerCredential>(decryptedJson);

                        if (dockerCredential != null)
                        {
                            var loginCmd = $"echo '{dockerCredential.Password}' | docker login {config.Registry} -u {dockerCredential.Username} --password-stdin";
                            ExecuteCommand(sshClient, loginCmd);
                            await SendLog(message, "Docker Registry 登录成功");
                        }
                    }
                    catch (Exception ex)
                    {
                        _logger.LogWarning(ex, "Docker 凭证处理失败");
                    }
                }

                var pullResult = ExecuteCommand(sshClient, $"docker pull {fullImageName}");
                await SendLog(message, pullResult);
            }

            // 3. 停止并删除旧容器（如果存在）
            if (!string.IsNullOrEmpty(config.ContainerName))
            {
                await SendLog(message, $"停止旧容器: {config.ContainerName}");
                ExecuteCommand(sshClient, $"docker stop {config.ContainerName} 2>/dev/null || true");
                ExecuteCommand(sshClient, $"docker rm {config.ContainerName} 2>/dev/null || true");
            }

            // 4. 运行新容器
            await SendLog(message, $"启动新容器: {config.ContainerName ?? "auto-generated"}");

            var dockerRunCmd = BuildDockerRunCommand(fullImageName, config);
            var runResult = ExecuteCommand(sshClient, dockerRunCmd);
            await SendLog(message, $"容器启动结果: {runResult}");

            // 5. 验证容器运行状态
            await Task.Delay(2000); // 等待容器启动
            var containerStatus = ExecuteCommand(sshClient,
                $"docker ps --filter \"name={config.ContainerName}\" --format \"{{{{.Status}}}}\"");

            if (string.IsNullOrEmpty(containerStatus) || !containerStatus.Contains("Up"))
            {
                var logs = ExecuteCommand(sshClient, $"docker logs {config.ContainerName} 2>&1 || echo 'No logs available'");
                await SendLog(message, $"容器日志:\n{logs}", "Warning");

                return new StepExecutionResult
                {
                    Success = false,
                    ErrorMessage = $"容器启动失败，状态: {containerStatus}"
                };
            }

            await SendLog(message, $"✅ 容器部署成功，状态: {containerStatus}");

            sshClient.Disconnect();

            return new StepExecutionResult
            {
                Success = true,
                Progress = 100,
                OutputContext = new Dictionary<string, string>
                {
                    ["DEPLOYED_IMAGE"] = fullImageName,
                    ["CONTAINER_NAME"] = config.ContainerName ?? "unknown",
                    ["REMOTE_HOST"] = config.RemoteHost,
                    ["CONTAINER_STATUS"] = containerStatus
                }
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Docker 远程部署处理器执行失败");
            return new StepExecutionResult
            {
                Success = false,
                ErrorMessage = $"部署失败: {ex.Message}"
            };
        }
    }

    private string ExecuteCommand(SshClient client, string command)
    {
        using var cmd = client.CreateCommand(command);
        var result = cmd.Execute();
        if (cmd.ExitStatus != 0 && !string.IsNullOrEmpty(cmd.Error))
        {
            _logger.LogWarning("命令执行警告: {Error}", cmd.Error);
        }
        return result.Trim();
    }

    private string BuildDockerRunCommand(string imageName, DockerDeployRemoteConfig config)
    {
        var cmd = new List<string> { "docker run -d" };

        // 容器名称
        if (!string.IsNullOrEmpty(config.ContainerName))
        {
            cmd.Add($"--name {config.ContainerName}");
        }

        // 端口映射
        if (config.PortMappings != null && config.PortMappings.Count > 0)
        {
            foreach (var port in config.PortMappings)
            {
                cmd.Add($"-p {port}");
            }
        }

        // 环境变量
        if (config.EnvironmentVariables != null && config.EnvironmentVariables.Count > 0)
        {
            foreach (var env in config.EnvironmentVariables)
            {
                cmd.Add($"-e {env.Key}='{env.Value}'");
            }
        }

        // 数据卷
        if (config.Volumes != null && config.Volumes.Count > 0)
        {
            foreach (var volume in config.Volumes)
            {
                cmd.Add($"-v {volume}");
            }
        }

        // 网络
        if (!string.IsNullOrEmpty(config.Network))
        {
            cmd.Add($"--network {config.Network}");
        }

        // 重启策略
        if (!string.IsNullOrEmpty(config.RestartPolicy))
        {
            cmd.Add($"--restart {config.RestartPolicy}");
        }
        else
        {
            cmd.Add("--restart unless-stopped");
        }

        // 额外的 Docker 运行参数
        if (config.ExtraDockerArgs != null && config.ExtraDockerArgs.Count > 0)
        {
            foreach (var arg in config.ExtraDockerArgs)
            {
                // 直接添加参数，支持任意 Docker 参数
                cmd.Add(arg);
            }
        }

        // 镜像名称
        cmd.Add(imageName);

        // 容器启动命令
        if (!string.IsNullOrEmpty(config.Command))
        {
            cmd.Add(config.Command);
        }

        return string.Join(" ", cmd);
    }

    private async Task SendLog(WorkflowStepDispatchMessage message, string logMessage, string level = "Info")
    {
        _logger.LogInformation("[Task {TaskId}] {Message}", message.TaskId, logMessage);
        await _taskExecutor.SendLogAsync(message.TaskId, message.StepId, logMessage, level);
    }
}

/// <summary>
/// Docker 远程部署配置
/// </summary>
public class DockerDeployRemoteConfig
{
    /// <summary>
    /// 远程主机地址
    /// </summary>
    public string RemoteHost { get; set; } = string.Empty;

    /// <summary>
    /// SSH 端口（默认 22）
    /// </summary>
    public int SshPort { get; set; } = 22;

    /// <summary>
    /// SSH 用户名（可选，如果有凭证则从凭证获取）
    /// </summary>
    public string? SshUsername { get; set; }

    /// <summary>
    /// SSH 密码（可选，如果有凭证则从凭证获取）
    /// </summary>
    public string? SshPassword { get; set; }

    /// <summary>
    /// 镜像仓库地址（可选）
    /// </summary>
    public string? Registry { get; set; }

    /// <summary>
    /// 镜像名称
    /// </summary>
    public string ImageName { get; set; } = string.Empty;

    /// <summary>
    /// 镜像标签（默认 latest）
    /// </summary>
    public string? Tag { get; set; }

    /// <summary>
    /// 容器名称
    /// </summary>
    public string? ContainerName { get; set; }

    /// <summary>
    /// 端口映射列表（例如: ["8080:80", "443:443"]）
    /// </summary>
    public List<string>? PortMappings { get; set; }

    /// <summary>
    /// 环境变量
    /// </summary>
    public Dictionary<string, string>? EnvironmentVariables { get; set; }

    /// <summary>
    /// 数据卷（例如: ["/host/path:/container/path"]）
    /// </summary>
    public List<string>? Volumes { get; set; }

    /// <summary>
    /// 网络名称
    /// </summary>
    public string? Network { get; set; }

    /// <summary>
    /// 重启策略（no, on-failure, always, unless-stopped）
    /// </summary>
    public string? RestartPolicy { get; set; }

    /// <summary>
    /// 容器启动命令（可选）
    /// </summary>
    public string? Command { get; set; }

    /// <summary>
    /// 额外的 Docker 运行参数
    /// 支持任意 docker run 参数，例如:
    /// ["-v /extra:/data", "--memory 512m", "--cpus 2", "--privileged", "--user 1000:1000"]
    /// </summary>
    public List<string>? ExtraDockerArgs { get; set; }
}

/// <summary>
/// SSH 凭证
/// </summary>
public class SshCredential
{
    public string Username { get; set; } = string.Empty;
    public string? Password { get; set; }
    public string? PrivateKeyPath { get; set; }
}

/// <summary>
/// Docker 凭证
/// </summary>
public class DockerCredential
{
    public string Registry { get; set; } = string.Empty;
    public string Username { get; set; } = string.Empty;
    public string Password { get; set; } = string.Empty;
}
